/* 测试好友管理子服务的客户端 */
#include <gflags/gflags.h>
#include <brpc/channel.h>
#include <thread>
#include <gtest/gtest.h>
#include "logger.hpp"
#include "brpc.hpp"
#include "etcd.hpp"
#include "base.pb.h"
#include "user.pb.h"
#include "message.pb.h"
#include "friend.pb.h"
#include "utils.hpp"

DEFINE_bool(run_mode, false, "程序的运行模式，false-调试；true-发布");
DEFINE_string(log_file, "", "发布模式下，用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下，用于指定日志输出等级");

DEFINE_string(etcd_host, "127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(friend_service, "/service/friend_service", "调用的服务目录");

ChatSystem::ServiceManager::ptr service_manager;
std::string event_id1;
std::string event_id2;
std::string event_id3;

// 如果你想暂时禁用某个具体的测试案例，可以直接在测试定义前加上 DISABLED_ 前缀。
TEST(DISABLED_好友管理子服务测试, 申请好友的测试) 
{
    auto channel = service_manager->choose(FLAGS_friend_service);
    ASSERT_TRUE(channel);

    //发起Friend Rpc调用
    // 2.实例化pb中的FriendService_Stub类对象；
    ChatSystem::FriendService_Stub stub(channel.get());
    // 3.发起rpc请求，获取响应进行处理；
    brpc::Controller cntl;
    ChatSystem::FriendAddReq req;
    ChatSystem::FriendAddRsp rsp;

    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("e1c3-abc29d99-0000");
    req.set_respondent_id("2191-36ead305-0001");

    stub.FriendAdd(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    event_id1 = rsp.notify_event_id();

    //一个 Controller 对象不能被重复使用，需要在再次使用之前调用Reset()方法进行重置；
    cntl.Reset();
    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("7c00-3d3550df-0002");
    req.set_respondent_id("2191-36ead305-0001");

    stub.FriendAdd(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    event_id2 = rsp.notify_event_id();


    //一个 Controller 对象不能被重复使用，需要在再次使用之前调用Reset()方法进行重置；
    cntl.Reset();
    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("d375-16be7f20-0003");
    req.set_respondent_id("2191-36ead305-0001");

    stub.FriendAdd(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    event_id3 = rsp.notify_event_id();

}

TEST(DISABLED_好友管理子服务测试, 获取好友申请列表的测试) 
{
    auto channel = service_manager->choose(FLAGS_friend_service);
    ASSERT_TRUE(channel);

    //发起Friend Rpc调用
    // 2.实例化pb中的FriendService_Stub类对象；
    ChatSystem::FriendService_Stub stub(channel.get());
    // 3.发起rpc请求，获取响应进行处理；
    brpc::Controller cntl;
    ChatSystem::GetPendingFriendEventListReq req;
    ChatSystem::GetPendingFriendEventListRsp rsp;

    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("2191-36ead305-0001");

    stub.GetPendingFriendEventList(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());

    for(int i = 0; i < rsp.event_size(); ++i)
    {
        std::cout << "---------------------------" << std::endl;
        std::cout << rsp.event(i).sender().user_id() << std::endl;
        std::cout << rsp.event(i).sender().nickname() << std::endl;
        std::cout << rsp.event(i).sender().avatar() << std::endl;
    }
}

TEST(DISABLED_好友管理子服务测试, 对好友申请进行处理的测试) 
{
    auto channel = service_manager->choose(FLAGS_friend_service);
    ASSERT_TRUE(channel);

    //发起Friend Rpc调用
    // 2.实例化pb中的FriendService_Stub类对象；
    ChatSystem::FriendService_Stub stub(channel.get());
    // 3.发起rpc请求，获取响应进行处理；
    brpc::Controller cntl;
    ChatSystem::FriendAddProcessReq req;
    ChatSystem::FriendAddProcessRsp rsp;

    req.set_request_id(ChatSystem::Util::uuid());
    req.set_notify_event_id(event_id1);
    req.set_agree(true);
    req.set_apply_user_id("e1c3-abc29d99-0000");
    req.set_user_id("2191-36ead305-0001");

    stub.FriendAddProcess(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    if(!rsp.new_chat_session_id().empty())
    {
        std::cout << rsp.new_chat_session_id() << std::endl;
    }

    //一个 Controller 对象不能被重复使用，需要在再次使用之前调用Reset()方法进行重置；
    cntl.Reset();
    req.set_request_id(ChatSystem::Util::uuid());
    req.set_notify_event_id(event_id1);
    req.set_agree(false);
    req.set_apply_user_id("7c00-3d3550df-0002");
    req.set_user_id("2191-36ead305-0001");

    stub.FriendAddProcess(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    if(!rsp.new_chat_session_id().empty())
    {
        std::cout << rsp.new_chat_session_id() << std::endl;
    }

    //一个 Controller 对象不能被重复使用，需要在再次使用之前调用Reset()方法进行重置；
    cntl.Reset();
    req.set_request_id(ChatSystem::Util::uuid());
    req.set_notify_event_id(event_id1);
    req.set_agree(true);
    req.set_apply_user_id("d375-16be7f20-0003");
    req.set_user_id("2191-36ead305-0001");

    stub.FriendAddProcess(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    if(!rsp.new_chat_session_id().empty())
    {
        std::cout << rsp.new_chat_session_id() << std::endl;
    }
}

TEST(DISABLED_好友管理子服务测试, 用户搜索的测试) 
{
    auto channel = service_manager->choose(FLAGS_friend_service);
    ASSERT_TRUE(channel);

    //发起Friend Rpc调用
    // 2.实例化pb中的FriendService_Stub类对象；
    ChatSystem::FriendService_Stub stub(channel.get());
    // 3.发起rpc请求，获取响应进行处理；
    brpc::Controller cntl;
    ChatSystem::FriendSearchReq req;
    ChatSystem::FriendSearchRsp rsp;

    req.set_request_id(ChatSystem::Util::uuid());
    req.set_search_key("猪");
    req.set_user_id("2191-36ead305-0001");

    stub.FriendSearch(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());

    std::cout << "通过猪妈妈来搜索用户: " << std::endl;
    for(int i = 0; i < rsp.user_info_size(); ++i)
    {
        std::cout << "---------------------------" << std::endl;
        std::cout << rsp.user_info(i).user_id() << std::endl;
        std::cout << rsp.user_info(i).nickname() << std::endl;
        std::cout << rsp.user_info(i).avatar() << std::endl;
    }

    //一个 Controller 对象不能被重复使用，需要在再次使用之前调用Reset()方法进行重置；
    cntl.Reset();
    req.set_request_id(ChatSystem::Util::uuid());
    req.set_search_key("猪");
    req.set_user_id("7c00-3d3550df-0002");

    stub.FriendSearch(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());

    std::cout << "通过小猪乔治来搜索用户: " << std::endl;
    for(int i = 0; i < rsp.user_info_size(); ++i)
    {
        std::cout << "---------------------------" << std::endl;
        std::cout << rsp.user_info(i).user_id() << std::endl;
        std::cout << rsp.user_info(i).nickname() << std::endl;
        std::cout << rsp.user_info(i).avatar() << std::endl;
    }
}

TEST(DISABLED_好友管理子服务测试, 获取好友列表的测试) 
{
    auto channel = service_manager->choose(FLAGS_friend_service);
    ASSERT_TRUE(channel);

    //发起Friend Rpc调用
    // 2.实例化pb中的FriendService_Stub类对象；
    ChatSystem::FriendService_Stub stub(channel.get());
    // 3.发起rpc请求，获取响应进行处理；
    brpc::Controller cntl;
    ChatSystem::GetFriendListReq req;
    ChatSystem::GetFriendListRsp rsp;

    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("2191-36ead305-0001");

    stub.GetFriendList(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());

    std::cout << "猪妈妈的好友列表：" << std::endl;
    for(int i = 0; i < rsp.friend_list_size(); ++i)
    {
        std::cout << "---------------------------" << std::endl;
        std::cout << rsp.friend_list(i).user_id() << std::endl;
        std::cout << rsp.friend_list(i).nickname() << std::endl;
        std::cout << rsp.friend_list(i).avatar() << std::endl;
    }

    //一个 Controller 对象不能被重复使用，需要在再次使用之前调用Reset()方法进行重置；
    cntl.Reset();
    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("d375-16be7f20-0003");

    stub.GetFriendList(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());

    std::cout << "小猪佩奇的好友列表：" << std::endl;
    for(int i = 0; i < rsp.friend_list_size(); ++i)
    {
        std::cout << "---------------------------" << std::endl;
        std::cout << rsp.friend_list(i).user_id() << std::endl;
        std::cout << rsp.friend_list(i).nickname() << std::endl;
        std::cout << rsp.friend_list(i).avatar() << std::endl;
    }

    //一个 Controller 对象不能被重复使用，需要在再次使用之前调用Reset()方法进行重置；
    cntl.Reset();
    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("7c00-3d3550df-0002");

    stub.GetFriendList(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());

    std::cout << "小猪乔治的好友列表：" << std::endl;
    for(int i = 0; i < rsp.friend_list_size(); ++i)
    {
        std::cout << "---------------------------" << std::endl;
        std::cout << rsp.friend_list(i).user_id() << std::endl;
        std::cout << rsp.friend_list(i).nickname() << std::endl;
        std::cout << rsp.friend_list(i).avatar() << std::endl;
    }
}

TEST(DISABLED_好友管理子服务测试, 删除好友的测试) 
{
    auto channel = service_manager->choose(FLAGS_friend_service);
    ASSERT_TRUE(channel);

    //发起Friend Rpc调用
    // 2.实例化pb中的FriendService_Stub类对象；
    ChatSystem::FriendService_Stub stub(channel.get());
    // 3.发起rpc请求，获取响应进行处理；
    brpc::Controller cntl;
    ChatSystem::FriendRemoveReq req;
    ChatSystem::FriendRemoveRsp rsp;

    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("2191-36ead305-0001");
    req.set_peer_id("d375-16be7f20-0003");

    stub.FriendRemove(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
}

TEST(DISABLED_好友管理子服务测试, 创建群聊的测试) 
{
    auto channel = service_manager->choose(FLAGS_friend_service);
    ASSERT_TRUE(channel);

    //发起Friend Rpc调用
    // 2.实例化pb中的FriendService_Stub类对象；
    ChatSystem::FriendService_Stub stub(channel.get());
    // 3.发起rpc请求，获取响应进行处理；
    brpc::Controller cntl;
    ChatSystem::ChatSessionCreateReq req;
    ChatSystem::ChatSessionCreateRsp rsp;

    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("e1c3-abc29d99-0000");
    req.set_chat_session_name("幸福一家猪");
    req.add_member_id_list("e1c3-abc29d99-0000");
    req.add_member_id_list("2191-36ead305-0001");
    req.add_member_id_list("7c00-3d3550df-0002");
    req.add_member_id_list("d375-16be7f20-0003");

    stub.ChatSessionCreate(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    std::cout << "---------------------------" << std::endl;
    std::cout << rsp.chat_session_info().chat_session_id() << std::endl;
    std::cout << rsp.chat_session_info().chat_session_name() << std::endl;
    std::cout << rsp.chat_session_info().avatar() << std::endl;
}

TEST(好友管理子服务测试, 获取聊天会话列表的测试) 
{
    auto channel = service_manager->choose(FLAGS_friend_service);
    ASSERT_TRUE(channel);

    //发起Friend Rpc调用
    // 2.实例化pb中的FriendService_Stub类对象；
    ChatSystem::FriendService_Stub stub(channel.get());
    // 3.发起rpc请求，获取响应进行处理；
    brpc::Controller cntl;
    ChatSystem::GetChatSessionListReq req;
    ChatSystem::GetChatSessionListRsp rsp;

    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("e1c3-abc29d99-0000");

    stub.GetChatSessionList(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    std::cout << "猪爸爸获取聊天会话列表：" << std::endl;
    for(int i = 0; i < rsp.chat_session_info_list_size(); ++i)
    {
        std::cout << "---------------------------" << std::endl;
        if(!rsp.chat_session_info_list(i).single_chat_friend_id().empty())
        {
            std::cout << rsp.chat_session_info_list(i).single_chat_friend_id() << std::endl;
        }
        std::cout << rsp.chat_session_info_list(i).chat_session_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).chat_session_name() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().message_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().chat_session_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().timestamp() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().sender().user_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().sender().nickname() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().sender().avatar() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().message().message_type() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().message().file_message().file_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().message().file_message().file_size() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().message().file_message().file_name() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().message().file_message().file_contents() << std::endl;
        std::cout << rsp.chat_session_info_list(i).avatar() << std::endl;
    }

}

TEST(DISABLED_好友管理子服务测试, 获取聊天会话成员的测试) 
{
    auto channel = service_manager->choose(FLAGS_friend_service);
    ASSERT_TRUE(channel);

    //发起Friend Rpc调用
    // 2.实例化pb中的FriendService_Stub类对象；
    ChatSystem::FriendService_Stub stub(channel.get());
    // 3.发起rpc请求，获取响应进行处理；
    brpc::Controller cntl;
    ChatSystem::GetChatSessionMemberReq req;
    ChatSystem::GetChatSessionMemberRsp rsp;

    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("e1c3-abc29d99-0000");
    req.set_chat_session_id("1379-15db9a3c-0005");

    stub.GetChatSessionMember(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    std::cout << "猪爸爸获取到的幸福一家猪聊天会话成员：" << std::endl;
    for(int i = 0; i < rsp.member_info_list_size(); ++i)
    {
        std::cout << "---------------------------" << std::endl;
        std::cout << rsp.member_info_list(i).user_id() << std::endl;
        std::cout << rsp.member_info_list(i).nickname() << std::endl;
        std::cout << rsp.member_info_list(i).avatar() << std::endl;
    }

    //一个 Controller 对象不能被重复使用，需要在再次使用之前调用Reset()方法进行重置；
    cntl.Reset();
    req.set_request_id(ChatSystem::Util::uuid());
    req.set_user_id("2191-36ead305-0001");
    req.set_chat_session_id("1379-15db9a3c-0005");

    stub.GetChatSessionMember(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    ASSERT_TRUE(rsp.success());
    std::cout << "猪妈妈获取到的幸福一家猪聊天会话成员：" << std::endl;
    for(int i = 0; i < rsp.member_info_list_size(); ++i)
    {
        std::cout << "---------------------------" << std::endl;
        std::cout << rsp.member_info_list(i).user_id() << std::endl;
        std::cout << rsp.member_info_list(i).nickname() << std::endl;
        std::cout << rsp.member_info_list(i).avatar() << std::endl;
    }
}

int main(int argc, char* argv[])
{
    testing::InitGoogleTest(&argc, argv);
    google::ParseCommandLineFlags(&argc, &argv, true);
    ChatSystem::InitLogger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);

    //1. 先去注册中心进行服务的发现---发现friend_server的服务器节点地址信息并实例化通信信道
    //1.1 先构造Rpc整体的服务管理信道类
    service_manager = std::make_shared<ChatSystem::ServiceManager>();
    service_manager->declared(FLAGS_friend_service);  //设置需要关心的服务
    auto put_cb = std::bind(&ChatSystem::ServiceManager::onServiceOnline, service_manager.get(), std::placeholders::_1, std::placeholders::_2);
    auto del_cb = std::bind(&ChatSystem::ServiceManager::onServiceOffline, service_manager.get(), std::placeholders::_1, std::placeholders::_2);
    //1.2 构造服务发现对象 
    ChatSystem::Discovery::ptr dclient = std::make_shared<ChatSystem::Discovery>(FLAGS_etcd_host, FLAGS_base_service, put_cb, del_cb);
    

    //开始所有的单元测试
    return RUN_ALL_TESTS();
}
